home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / dev / cross / GBDK-2.0.lha / GBDK / lib / div.s < prev    next >
Text File  |  1998-10-01  |  4KB  |  161 lines

  1.     .include    "global.s"
  2.  
  3.     .area    _CODE
  4.  
  5.     ;; 16-bit division
  6.     ;; 
  7.     ;; Entry conditions
  8.     ;;   BC = dividend
  9.     ;;   DE = divisor
  10.     ;; 
  11.     ;; Exit conditions
  12.     ;;   BC = quotient
  13.     ;;   DE = remainder
  14.     ;;   If divisor is non-zero, carry=0
  15.     ;;   If divisor is 0, carry=1 and both quotient and remainder are 0
  16.     ;;
  17.     ;; Register used: AF,BC,DE,HL
  18. .div16::
  19. .mod16::
  20.     ;; Determine sign of quotient by xor-ing high bytes of dividend
  21.     ;;  and divisor. Quotient is positive if signs are the same, negative
  22.     ;;  if signs are different
  23.     ;; Remainder has same sign as dividend
  24.     LD    A,B        ; Get high byte of dividend
  25.     LD    (.srem),A    ; Save as sign of remainder
  26.     XOR    D        ; Xor with high byte of divisor
  27.     LD    (.squot),A    ; Save sign of quotient
  28.     ;; Take absolute value of divisor
  29.     BIT    7,D
  30.     JP    Z,.chkde    ; Jump if divisor is positive
  31.     SUB    A        ; Substract divisor from 0
  32.     SUB    E
  33.     LD    E,A
  34.     SBC    A        ; Propagate borrow (A=0xFF if borrow)
  35.     SUB    D
  36.     LD    D,A
  37.     ;; Take absolute value of dividend
  38. .chkde:
  39.     BIT    7,B
  40.     JP    Z,.dodiv    ; Jump if dividend is positive
  41.     SUB    A        ; Substract dividend from 0
  42.     SUB    C
  43.     LD    C,A
  44.     SBC    A        ; Propagate borrow (A=0xFF if borrow)
  45.     SUB    B
  46.     LD    B,A
  47.     ;; Divide absolute values
  48. .dodiv:
  49.     CALL    .divu16
  50.     RET    C        ; Exit if divide by zero
  51.     ;; Negate quotient if it is negative
  52.     LD    A,(.squot)
  53.     AND    #0x80
  54.     JP    Z,.dorem    ; Jump if quotient is positive
  55.     SUB    A        ; Substract quotient from 0
  56.     SUB    C
  57.     LD    C,A
  58.     SBC    A        ; Propagate borrow (A=0xFF if borrow)
  59.     SUB    B
  60.     LD    B,A
  61. .dorem:
  62.     ;; Negate remainder if it is negative
  63.     LD    A,(.srem)
  64.     AND    #0x80
  65.     RET    Z        ; Return if remainder is positive
  66.     SUB    A        ; Substract remainder from 0
  67.     SUB    E
  68.     LD    E,A
  69.     SBC    A        ; Propagate remainder (A=0xFF if borrow)
  70.     SUB    D
  71.     LD    D,A
  72.     RET
  73. .divu16::
  74. .modu16::
  75.     ;; Check for division by zero
  76.     LD    A,E
  77.     OR    D
  78.     JR    NZ,.divide    ; Branch if divisor is non-zero
  79.     LD    BC,#0x00    ; Divide by zero error
  80.     LD    D,B
  81.     LD    E,C
  82.     SCF            ; Set carry, invalid result
  83.     RET
  84. .divide:
  85.     LD    L,C        ; L = low byte of dividend/quotient
  86.     LD    H,B        ; H = high byte of dividend/quotient
  87.     LD    BC,#0x00    ; BC = remainder
  88.     OR    A        ; Clear carry to start
  89.     LD    A,#16        ; 16 bits in dividend
  90. .dvloop:
  91.     ;; Shift next bit of quotient into bit 0 of dividend
  92.     ;; Shift next MSB of dividend into LSB of remainder
  93.     ;; BC holds both dividend and quotient. While we shift a bit from
  94.     ;;  MSB of dividend, we shift next bit of quotient in from carry
  95.     ;; HL holds remainder
  96.     ;; Do a 32-bit left shift, shifting carry to L, L to H,
  97.     ;;  H to C, C to B
  98.     LD    (.dcnt),A
  99.     RL    L        ; Carry (next bit of quotient) to bit 0
  100.     RL    H        ; Shift remaining bytes
  101.     RL    C
  102.     RL    B        ; Clears carry since BC was 0
  103.     ;; If remainder is >= divisor, next bit of quotient is 1. This
  104.     ;;  bit goes to carry
  105.     PUSH    BC        ; Save current remainder
  106.     LD    A,C        ; Substract divisor from remainder
  107.     SBC    E
  108.     LD    C,A
  109.     LD    A,B
  110.     SBC    D
  111.     LD    B,A
  112.     CCF            ; Complement borrow so 1 indicates a
  113.                 ;  successful substraction (this is the
  114.                 ;  next bit of quotient)
  115.     JR    C,.drop        ; Jump if remainder is >= dividend
  116.     POP    BC        ; Otherwise, restore remainder
  117.     JR    .nodrop
  118. .drop:
  119.     INC    SP
  120.     INC    SP
  121. .nodrop:
  122.     LD    A,(.dcnt)
  123.     DEC    A        ; DEC does not affect carry flag
  124.     JR    NZ,.dvloop
  125.     ;; Shift last carry bit into quotient
  126.     LD    D,B        ; DE = remainder
  127.     LD    E,C
  128.     RL    L        ; Carry to L
  129.     LD    C,L        ; C = low byte of quotient
  130.     RL    H
  131.     LD    B,H        ; B = high byte of quotient
  132.     OR    A        ; Clear carry, valid result
  133.     RET
  134.  
  135. .div8::
  136. .mod8::
  137.     LD    A,C        ; Sign extend
  138.     RLCA
  139.     SBC    A
  140.     LD    B,A
  141.     LD    A,E        ; Sign extend
  142.     RLCA
  143.     SBC    A
  144.     LD    D,A
  145.     JP    .div16
  146.  
  147. .divu8::
  148. .modu8::
  149.     LD    B,#0x00
  150.     LD    D,#0x00
  151.     JP    .divu16
  152.  
  153.     .area    _BSS
  154.  
  155. .srem:
  156.     .ds 0x01        ; Sign of quotient
  157. .squot:
  158.     .ds 0x01        ; Sign of remainder
  159. .dcnt:
  160.     .ds 0x01        ; Counter for division
  161.